<?php

use Doraemon\tools\OpenTracing\OpenTracingSDK;
use Doraemon\tools\OpenTracing\OpenTracingTag;
use Doraemon\tools\Log;
use NlvLogger\Trace\HtraceWrapper;

abstract class ActionPlugin extends Yaf_Action_Abstract
{
    const API_CODE_SUCCESS = 1;

    //是否开启链路追踪，针对某些接口可能需要强制开启链路
    const IS_TRACING = null;

    //获取get/post全部传参
    protected $params = [];

    //获取消息体
    protected $messageBody = [];

    protected $requestId;
    protected $requestTime;
    protected $channelId;

    abstract public function main();

    public function execute()
    {
        $host = $_SERVER['HTTP_X_FORWARDED_HOST'] ?? 'localhost';
        $serviceName = explode('.', $host)[0];
        $sampleSet = !is_null(static::IS_TRACING) ? static::IS_TRACING : null;
        $tracing = OpenTracingSDK::createTracing($serviceName, $sampleSet);
        $rootSpan = OpenTracingSDK::commonAddTracer($tracing, 'rootSpan', [
            OpenTracingTag::TAG_BIZ_KEY => $_SERVER['APP_NAME'] ?? 'shapi',
            OpenTracingTag::TAG_REQUEST_METHOD => $this->getRequest()->getMethod() ?? 'POST',
            OpenTracingTag::TAG_REQUEST_HOST => $host,
            OpenTracingTag::TAG_REQUEST_URL => $this->getRequest()->getRequestUri() ?? '',
        ]);

        $this->getResponse()->setHeader('Content-Type', 'application/json;charset=utf8');

        // 临时通过apiaction当接入层，为每次请求产生一个"唯一"id，注意：该"唯一"id有较高重复概率
        // app端口添加的http header key为X-Request-Id，服务器端上线时间早，名字叫做Trace，所以映射一下即可
        $sTraceId = $_SERVER['HTTP_X_REQUEST_ID'] ?? md5(time() . mt_rand(1000, 9999));
        $_SERVER['HTTP_TRACEID'] = $sTraceId;
        $oTraceWrapper = HtraceWrapper::getInstance();
        $oTraceWrapper->setTraceId($sTraceId);

        try {
            //获取参数
            $reqParams = $this->getRequest()->getPost();
            if (!$reqParams) $reqParams = $this->getRequest()->getQuery();

            $this->params = $reqParams ?: [];
            $this->messageBody = json_decode($reqParams['message_body'], true) ?: [];
            $this->requestId = $reqParams['request_id'] ?: '';
            $this->requestTime = $reqParams['request_time'] ?: 0;
            $this->channelId = $reqParams['channel_id'] ?: 0;

            $this->main();

            Log::event_execSuccess_debug(static::class, [
                "uri" => $this->getRequest()->getRequestUri(),
                "params" => $this->getRequest()->getPost()
            ]);
        } catch (\Exception $e) {
            Log::event_execError_error(static::class, [
                "uri" => $this->getRequest()->getRequestUri(),
                "params" => $this->getRequest()->getPost(),
                "error" => $e
            ]);
            $this->setError($e->getCode(), $e->getMessage(), $e->getLine());
        }
        //追加请求参数标签
        OpenTracingSDK::pushSpanTags($rootSpan, OpenTracingTag::TAG_REQUEST_PARAMS, $this->params, true);
        OpenTracingSDK::finishSpan($rootSpan);
        OpenTracingSDK::flushTracer($tracing);
    }

    protected function setSuccess($data = NULL)
    {
        $this->getResponse()->setBody(json_encode([
            "code" => self::API_CODE_SUCCESS,
            "data" => $data
        ], JSON_UNESCAPED_UNICODE));
    }

    protected function setError($code, $message, $line)
    {
        $this->getResponse()->setBody(json_encode([
            "code" => $line,
            "msg" => $message
        ], JSON_UNESCAPED_UNICODE));
    }
}